<?php
namespace gnomephp\appcommand;


use Symfony\Component\Console\Input\InputArgument,
Symfony\Component\Console\Input\InputOption,
Symfony\Component\Console,
Doctrine\ORM\Tools\Console\MetadataFilter;

/**
 * Command to install and remove "features"
 */
class FeatureCommand extends AbstractCommand
{
	
	/**
	 * List of available features.
	 * 
	 * @var array
	 */
	protected $available_features = array('crud', 'security', 'captcha');
	
	/**
	 * @see Console\Command\Command
	 */
	protected function configure()
	{
		$this
		->setName('app:feature')
		->setDescription('You may choose to install features right out of the box. This will copy source files to your application.')
		->setDefinition(array(
		new InputArgument(
                'method', InputArgument::REQUIRED,
                'list, install or remove'
                ),
                new InputArgument(
                'feature', InputArgument::OPTIONAL,
                'What feature to install / remove. This argument is required if install or remove method is used.'
                ),
                )
                )
                ->setHelp(<<<EOT
A feature is a set of classes or single class that adds specific features to your application.

This saves you for lots of coding the same classes. 
The minimum code for each feature you choose to install will be added to your application.
EOT
                );
	}

	/**
	 * @see Console\Command\Command
	 */
	protected function execute(Console\Input\InputInterface $input, Console\Output\OutputInterface $output){
		$method = $input->getArgument('method');
		$feature = $input->getArgument('feature');



		
		switch($method){
			case 'list':
				$output->write('Available features:' . PHP_EOL);
				foreach($this->available_features as $f){
					$output->write(' - ' . $f . PHP_EOL);
				}
				break;
			case 'install':
			case 'remove':

				if (!$feature)throw new \InvalidArgumentException("You will need to include what feature you'd like to $method as a seccond argument.");
				if (!in_array($feature, $this->available_features)){
					throw new \InvalidArgumentException(
						sprintf("The feature %s does not exist in the available features list. Available features is: %s", $feature, implode(' ,', $this->available_features)));
				}
				
				$output->write(PHP_EOL . $method.'ing feature  ' . $feature . ' ...' . PHP_EOL);

				$xml = simplexml_load_file(GNOME_FW_PATH . DIRECTORY_SEPARATOR . 'res' . DIRECTORY_SEPARATOR . 'features' . DIRECTORY_SEPARATOR . $feature . '.xml');

				$featurePath = GNOME_FW_PATH . DIRECTORY_SEPARATOR . 'res' . DIRECTORY_SEPARATOR . 'features' . DIRECTORY_SEPARATOR . $feature . DIRECTORY_SEPARATOR;
				foreach($xml->$method->children() as $instruction){
					
					switch($instruction->getName()){
						case 'copy':
							$to = $this->getAppPath() . DIRECTORY_SEPARATOR . $instruction->to;
							$from = $featurePath . $instruction->from;
							if (file_exists($to)){
								$output->write("WARNING: Did not copy $from to $to , since $to exists already.." . PHP_EOL);
							}else{
								$src = file_get_contents($from);
								foreach($instruction->attributes() as $key => $value){
									switch($key){
										case 'parseNS':
											$src = $this->parseNS($src);
											$output->write("Parsing namespace on $from ..." . PHP_EOL);
											break;
									}
								}
								$output->write("Saving file to $to." . PHP_EOL);
								file_put_contents($to, $src);
							}
							break;
						case 'msg':
							$output->write((string)$instruction);
							break;
						case 'del':
							$f = $this->getAppPath() . DIRECTORY_SEPARATOR . $instruction;
							if (file_exists($f)){
								$output->write("Removing file $f." . PHP_EOL);
								unlink($f);
							}
							else $output->write("NOTICE: Did not delete $f because it does not exists." . PHP_EOL);
							break;
						case 'router':
							$routerFile = $this->getAppPath() . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'routes.php';
							$src = file_get_contents($routerFile);
							foreach($instruction->children() as $routerInstruction){
								switch($routerInstruction->getName()){
									case 'add':

										if (!strstr($src, trim($routerInstruction))){
											$src .= "\n$routerInstruction";
											$output->write("Adding routes.php configuration settings to your config/routes.php file. Settings added:\n----\n$routerInstruction\n----" . PHP_EOL);
										}else{
											$output->write('NOTICE: Already got router config appended to the config file.' . PHP_EOL);
										}
										break;
									case 'del':
										if (!strstr($src, trim($routerInstruction))){
											$output->write('NOTICE: could not remove the following line from routes.php: ' . "\n----\n" . $routerInstruction . "\n----\n" . PHP_EOL);
										}else{
											$src = str_replace(trim($routerInstruction), '', $src);
											$output->write('Removed routes.php configuration for this feature.' . PHP_EOL);
										}
										break;
								}
							}
							file_put_contents($routerFile, $src);
							break;
					}
				}

				$output->write("Done doing tasks for $method on feature $feature." . PHP_EOL);
				break;
			default:
				throw new \InvalidArgumentException("$method is not a valid argument for app:feature");
		}





	}

	
	protected function parseNS($src){
		return str_replace('__APP_NAME__', $this->getAppNS(), $src);
	}
	
	
}